Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make continuous recording handle bad timestamps gracefully #708

Merged
merged 2 commits into from
Oct 22, 2024

Conversation

andrey-utkin
Copy link
Contributor

The user-visible effect is that the recordings stick to the prescribed duration rather than randomly cut short.
The problem was that bad timestamps (situation which also occurs when just using ffmpeg) were attempted to be handled gracefully but were not done exactly right.

The problem looks like this when debug is enabled (-l debug):

D(3/camera_name): av_interleaved_write_frame: dts=47160000 pts=47160000 tb=1/90000 s_i=0 k=0
D(3/camera_name): [libav] unknown tcp_read_packet:
D(3/camera_name): [libav] unknown ret=1 c=24 [$]
D(3/camera_name): [libav] unknown id=0 len=886
D(3/camera_name): [libav] unknown nal 1
D(3/camera_name): av_interleaved_write_frame: dts=47174400 pts=47174400 tb=1/90000 s_i=0 k=0
D(3/camera_name): [libav] unknown tcp_read_packet:
D(3/camera_name): [libav] unknown ret=1 c=24 [$]
D(3/camera_name): [libav] unknown id=0 len=895
D(3/camera_name): [libav] error Application provided invalid, non monotonically increasing dts to muxer in stream 0: 47174400 >= 47174400
W(3/camera_name): Likely timestamping error. Ignoring.
D(3/camera_name): av_interleaved_write_frame: dts=47174400 pts=47174400 tb=1/90000 s_i=0 k=0
D(3/camera_name): [libav] error Application provided invalid, non monotonically increasing dts to muxer in stream 0: 47174400 >= 47174400
E(3/camera_name): Error writing frame to recording: Invalid argument
E(3/camera_name): Failure in recording writing
The original problem that caused the continuous recording chunks to end
earlier than their scheduled duration was that
- on some streams, sometimes packets with invalid timestamps come in
  (not monotonically increasing);
- upon failure of muxing a packet with invalid timestamp, recording
  muxing context bailed out.

The bailing out issue has been rectified in the previous commit.
Ignoring the -EINVAL return from av_interleaved_write_frame() may result
in some data loss (would need further research to figure out what's the
data which is lost) which would be confined to one GOP (group of frames)
and not have any effect after the next keyframe.

It requires explanation why such muxing failures occureed despite there
being code (replaced in this commit) which tries to handle this situation.

The code went most of the way, but crucially, it steps in to change the
timestamp if the new packet's timestamp is *less* than the last muxed
packet's:

    if (opkt.pts < last_video_pts || opkt.dts < last_video_dts)

This misses the case of the new packet's timestamp being *equal* to the
last muxed packet's timestamp.

The original code also isn't explicit about NOPTS handling - the notion
of packets not having any defined timestamp, which is represented by
AV_NOPTS_VALUE, same as INT64_MIN, equal to -9223372036854775808.

This commit makes handling of irregular timestamps to follow
ffmpeg's ffmpeg_mux.c:
- don't look at pts, manage only dts;
- don't change AV_NOPTS_VALUE, pass it on to av_interleaved_write_frame(),
  there is some logic in compute_muxer_pkt_fields() for that.

Aside from that, the variables to track last audio and video timestamp
were moved into a single array, to avoid the pre-existing duplication of
the code. (As a note, this logic is unlikely to ever be triggered for
audio.)
@andrey-utkin andrey-utkin merged commit 1865a97 into bluecherrydvr:master Oct 22, 2024
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants